#include "ringbuffer.h"
#include <stdlib.h>
#include <string.h>

static inline uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }

static inline uint32_t roundup_power_of_two(uint32_t num) {
  if (num == 0)
    return 2;
  // return 1 << (32 - __builtin_clz(num - 1));
  int i = 0;
  for (; num != 0; i++, (void)(num >>= 1)) {
  }
  return 1U << i;
}

static uint32_t ring_buffer_remain(ring_buffer_t *buf) {
  return buf->size - ring_buffer_len(buf);
}
static uint32_t ring_buffer_empty(ring_buffer_t *buf) {
  return buf->head == buf->tail;
}

ring_buffer_t *ring_buffer_new(uint32_t size) {
  size = roundup_power_of_two(size);
  ring_buffer_t *buf = (ring_buffer_t *)malloc(size);
  if (!buf)
    return NULL;
  buf->size = size;
  buf->head = buf->tail = 0;
  buf->buf = (uint8_t *)malloc(size);
  return buf;
}

void ring_buffer_free(ring_buffer_t *buf) {
  if (!buf)
    return;
  if (buf->buf)
    free(buf->buf);
  free(buf);
}

uint32_t ring_buffer_len(ring_buffer_t *buf) { return buf->tail - buf->head; }

int ring_buffer_add(ring_buffer_t *buf, const void *data, uint32_t datlen) {
  if (ring_buffer_remain(buf) < datlen)
    return 0;
#if 0
  uint32_t i = min(datlen, buf->size - (buf->tail % buf->size));
  memcpy(buf->buf + (buf->tail % buf->size), data, i);
  memcpy(buf->buf, data + i, datlen - i);
#else
  if (datlen <=
      buf->size -
          (buf->tail % buf->size)) { // 当前数据包大小大于队尾到buf尾部的距离
    memcpy(buf->buf + (buf->tail % buf->size), data, datlen);
  } else {
    uint32_t i = buf->size - (buf->tail % buf->size);
    memcpy(buf->buf + (buf->tail % buf->size), data, i);
    memcpy(buf->buf, data + i, datlen - i);
  }
#endif
  buf->tail += datlen;
  return datlen;
}

int ring_buffer_remove(ring_buffer_t *buf, void *data, uint32_t datlen) {
  if (ring_buffer_empty(buf))
    return 0;
  datlen = min(datlen, ring_buffer_len(buf));
#if 0
  uint32_t i = min(datlen, buf->size - (buf->head % buf->size));
  memcpy(data, buf->buf + (buf->head % buf->size), i);
  memcpy(data + i, buf->buf, datlen - i);
#else
  if (datlen <= buf->size - (buf->head % buf->size)) {
    memcpy(data, buf->buf + (buf->head % buf->size), datlen);
  } else {
    uint32_t i = buf->size - (buf->head % buf->size);
    memcpy(data, buf->buf + (buf->head % buf->size), i);
    memcpy(data + i, buf->buf, datlen - i);
  }
#endif
  buf->head += datlen;
  return datlen;
}

int ring_buffer_drain(ring_buffer_t *buf, uint32_t len) {
  return ring_buffer_remove(buf, NULL, len);
}

// 在buf中搜索sep
int ring_buffer_search(ring_buffer_t *buf, const char *sep, const int seplen) {
  uint32_t first = buf->head;
  uint32_t last = buf->tail;
  for (; first != last; first += seplen) {
    uint32_t end = first + seplen;
    if (seplen > buf->size - (first % buf->size)) {
      uint32_t remain = buf->size - (first % buf->size);
      if (!memcpy(buf + (first % buf->size), sep, remain) &&
          !memcpy(buf + (buf->head % buf->size), sep + remain,
                  seplen - remain)) {
        return first;
      }
    } else {
      if (memcmp(buf + (first % buf->size), sep, seplen) == 0) {
        return first;
      }
    }
  }
  return first;
}

uint8_t *ring_buffer_write_atmost(ring_buffer_t *buf) {
  // TODO: impl
  return NULL;
}